//
//  myTaskController.m
//  pacc
//
//  Created by 测试 on 2018/5/17.
//  Copyright © 2018年 测试. All rights reserved.
//

#import "myTaskController.h"
#import <CoreData/CoreData.h>
#import "Person+CoreDataClass.h"
#import "Hospital+CoreDataClass.h"
#import "SlideBarCell.h"

@interface myTaskController ()<UITableViewDelegate,UITableViewDataSource,NSFetchedResultsControllerDelegate>
@property (nonatomic, strong) NSManagedObjectContext *companyMOC;
@property (strong, nonatomic) NSFetchedResultsController *fetchedResultController;

@property (nonatomic, strong) NSArray *tDataSource;
@property (strong, nonatomic)  UITableView *myTableView;

@end

@implementation myTaskController

- (void)viewDidLoad {
    
    [super viewDidLoad];
    for (int i = 0; i < 1; i++) {
        Person *person    = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.companyMOC];
        person.name    = [NSString stringWithFormat:@"lxz %d", i];
        person.height         = i + 15;
        person.sectionName = [NSString stringWithFormat:@"%d", i % 5];
    }
    
    NSError *error = nil;
    if (self.companyMOC.hasChanges) {
        [self.companyMOC save:&error];
    }
    
    [self creatTableView];
}
#pragma mark -tableview-
-(void)creatTableView{
    UITableView *tableView = [[UITableView alloc]initWithFrame:self.view.frame];
    _myTableView = tableView;
    tableView.delegate = self;
    tableView.dataSource = self;
    tableView.backgroundColor = baseBackgroundColor;
    [self.view addSubview: tableView];
}
#pragma mark - ----- Create CoreData Context ------

/**
 创建上下文对象
 */
- (NSManagedObjectContext *)contextWithModelName2:(NSString *)modelName {
    // 创建上下文对象，并发队列设置为主队列
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    
    // 创建托管对象模型，并使用Company.momd路径当做初始化参数
    NSURL *modelPath = [[NSBundle mainBundle] URLForResource:modelName withExtension:@"momd"];
    NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelPath];
    
    // 创建持久化存储调度器
    NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
    
    // 创建并关联SQLite数据库文件，如果已经存在则不会重复创建
    NSString *dataPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
    dataPath = [dataPath stringByAppendingFormat:@"/%@.sqlite", modelName];
    [coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:dataPath] options:nil error:nil];
    
    // 上下文对象设置属性为持久化存储器
    
    context.persistentStoreCoordinator = coordinator;
    
    return context;
}
#pragma mark - ----- Create CoreData Context ------

/**
 创建上下文对象
 */
- (NSManagedObjectContext *)contextWithModelName:(NSString *)modelName {
    // 创建上下文对象，并发队列设置为主队列
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    
    // 创建托管对象模型，并使用Company.momd路径当做初始化参数
    NSURL *modelPath = [[NSBundle mainBundle] URLForResource:modelName withExtension:@"momd"];
    NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelPath];
    
    // 创建持久化存储调度器
    NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
    
    // 创建并关联SQLite数据库文件，如果已经存在则不会重复创建
    NSString *dataPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
    dataPath = [dataPath stringByAppendingFormat:@"/%@.sqlite", modelName];
    [coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:dataPath] options:nil error:nil];
    
    // 上下文对象设置属性为持久化存储器
    context.persistentStoreCoordinator = coordinator;
    
    return context;
}
- (NSManagedObjectContext *)companyMOC {
    if (!_companyMOC) {
        _companyMOC = [self contextWithModelName:@"Model"];
    }
    return _companyMOC;
}
#pragma mark - ----- NSFetchedResultsController ------
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    int i= 0;
    Person *person    = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.companyMOC];
    person.name    = [NSString stringWithFormat:@"lxz %d", i];
    person.height         = i + 15;
    person.sectionName = [NSString stringWithFormat:@"%d", i % 5];
//}
//- (IBAction)refreshView:(UIButton *)sender {
    // 创建请求对象，并指明操作User表
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"];
    
    // 设置排序规则，指明根据age字段升序排序
    NSSortDescriptor *heightSort = [NSSortDescriptor sortDescriptorWithKey:@"height" ascending:YES];
    request.sortDescriptors = @[heightSort];
    
    // 创建NSFetchedResultsController控制器实例，并绑定MOC
    NSError *error = nil;
    self.fetchedResultController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                                       managedObjectContext:self.companyMOC
                                                                         sectionNameKeyPath:@"sectionName"
                                                                                  cacheName:nil];
    // 设置代理，并遵守协议
    self.fetchedResultController.delegate = self;
    // 执行获取请求，执行后FRC会从持久化存储区加载数据，其他地方可以通过FRC获取数据
    [self.fetchedResultController performFetch:&error];
    
    // 错误处理
    if (error) {
        NSLog(@"NSFetchedResultsController init error : %@", error);
    }
    
    // 刷新UI
    [self.myTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"identifier"];
    [self.myTableView reloadData];
}

// 这里是简单模拟UI删除cell后，本地持久化区数据和UI同步的操作。在调用下面MOC保存上下文方法后，FRC会回调代理方法并更新UI
//- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
//    
//    if (editingStyle == UITableViewCellEditingStyleDelete) {
//        // 删除托管对象
//        Person *person = [self.fetchedResultController objectAtIndexPath:indexPath];
//        [self.companyMOC deleteObject:person];
//        
//        // 保存上下文环境，并做错误处理
//        NSError *error = nil;
//        if (![self.companyMOC save:&error]) {
//            NSLog(@"tableView delete cell error : %@", error);
//        }
//    }
//}

#pragma mark - ----- NSFetchedResultsControllerDelegate ------

// Cell数据源发生改变会回调此方法，例如添加新的托管对象等
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(nullable NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(nullable NSIndexPath *)newIndexPath {
    
    switch (type) {
        case NSFetchedResultsChangeInsert:
            [self.myTableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        case NSFetchedResultsChangeDelete:
            [self.myTableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        case NSFetchedResultsChangeMove:
            [self.myTableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            [self.myTableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        case NSFetchedResultsChangeUpdate: {
            Person *person = [self.fetchedResultController objectAtIndexPath:indexPath];
            
            UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath];
            cell.textLabel.text = person.name;
            [self.myTableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
        }
            break;
    }
}

// Section数据源发生改变回调此方法，例如修改section title等
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
    
    switch (type) {
        case NSFetchedResultsChangeInsert:
            [self.myTableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        case NSFetchedResultsChangeDelete:
            [self.myTableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        default:
            break;
    }
}

// 本地数据源发生改变，将要开始回调FRC代理方法。
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    [self.myTableView beginUpdates];
}

// 本地数据源发生改变，FRC代理方法回调完成。
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.myTableView endUpdates];
}

// 返回section的title，可以在这里对title做进一步处理。这里修改title后，对应section的indexTitle属性会被更新。
- (nullable NSString *)controller:(NSFetchedResultsController *)controller sectionIndexTitleForSectionName:(NSString *)sectionName {
    return [NSString stringWithFormat:@"sectionName %@", sectionName];
}

#pragma mark - ----- 生成测试数据 ------

- (IBAction)createTestData:(UIButton *)sender {
    for (int i = 0; i < 5; i++) {
        Person *person    = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.companyMOC];
        person.name    = [NSString stringWithFormat:@"lxz %d", i];
        person.height         = i + 15;
        person.sectionName = [NSString stringWithFormat:@"%d", i % 5];
    }
    
    NSError *error = nil;
    if (self.companyMOC.hasChanges) {
        [self.companyMOC save:&error];
    }
}
#pragma mark - ----- CRUD ------

/**
 添加Student实例
 */
- (IBAction)schoolAdd:(UIButton *)sender {
    // 创建托管对象，并指明创建的托管对象所属实体名
    Person *person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.companyMOC];
    person.name = @"lxz";
    // 实体中所有基础数据类型，创建类文件后默认都是NSNumber类型的
    person.age = 23;
    person.sectionName = @"7";
    
    // 通过上下文保存对象，并在保存前判断是否有更改
    NSError *error = nil;
    if (self.companyMOC.hasChanges) {
        [self.companyMOC save:&error];
    }
    
    // 错误处理，可以在这实现自己的错误处理逻辑
    if (error) {
        NSLog(@"CoreData Insert Data Error : %@", error);
    }
}
/**
 查找Student实例
 */
- (IBAction)schoolSearch:(UIButton *)sender {
    // 建立获取数据的请求对象，指明操作的实体为Student
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"];
    
    // 执行获取操作，获取所有Student托管对象
    NSError *error = nil;
    NSArray<Person *> *persons = [self.companyMOC executeFetchRequest:request error:&error];
    
    // 遍历输出查询结果
    [persons enumerateObjectsUsingBlock:^(Person * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"Student Name : %@, height : %f,sectionName : %@", obj.name, obj.height,obj.sectionName);
    }];
    
    // 错误处理
    if (error) {
        NSLog(@"CoreData Ergodic Data Error : %@", error);
    }
}

 #pragma mark --tableView delegate--
 
 // 通过FRC的sections数组属性，获取所有section的count值，将其设置为section number
 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
     return self.fetchedResultController.sections.count;
 }
 
 // 通过当前section的下标从sections数组中取出对应的section对象，并从section对象中获取所有对象count，将其设置为row number
 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
     return self.fetchedResultController.sections[section].numberOfObjects;
 }
 
 // FRC根据indexPath获取托管对象，并给cell赋值
 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     Person *person = [self.fetchedResultController objectAtIndexPath:indexPath];
//     UITableViewCell *cell     = [tableView dequeueReusableCellWithIdentifier:@"identifier" forIndexPath:indexPath];
     BOOL nibsRegistered=NO;
     if (!nibsRegistered) {
         UINib *nib=[UINib nibWithNibName:@"SlideBarCell" bundle:nil];
         [tableView registerNib:nib forCellReuseIdentifier:@"SlideBarCell"];
         nibsRegistered=YES;
     }
     
     SlideBarCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SlideBarCell"];
     cell.textLabel.text       = person.name;
     cell.detailTextLabel.text = [NSString stringWithFormat:@"%f", person.height];
     return cell;
 }
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 100;
}
 // 创建FRC对象时，通过sectionNameKeyPath:传递进去的section title的属性名，在这里获取对应的属性值
 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
     return self.fetchedResultController.sections[section].indexTitle;
 }
 
 // 是否可以编辑
 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
     return YES;
 }
 
 

#pragma mark - private method
- (void)setupTestData {
    
    NSMutableArray *tempArray = [NSMutableArray array];
    for (int i = 0; i < 20; i ++) {
        NSString *title = [NSString stringWithFormat:@"热点%d",i];
        
        NSMutableArray *arr = [NSMutableArray array];
        for (int j = 0; j < 20 + i; j ++) {
            NSString *content = [NSString stringWithFormat:@"index%d",j];
            [arr addObject:content];
        }
        
        NSDictionary *dic = @{
                              @"title":title,
                              @"data":arr
                              };
        [tempArray addObject:dic];
    }
    self.tDataSource = [tempArray copy];
}



- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end
